package back;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.LoggerFactory;
import sardine.Route;
import sardine.log.Logs;
import wordfilter.dfa.Sensitives;

import java.io.File;
import java.io.FileInputStream;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;

import static sardine.Sardine.*;

/**
 * @auth bruce-sha
 * @date 2015/6/23
 */
public class Main {

    static String APP_HOME;

    public static void main(String[] args) {
        //TODO debug模式
//        System.setProperty("app.home", "D:/buru/gitosc/wordfilter");
        config();
        String port = System.getProperty("sardine.port", "9119");
        port(Integer.parseInt(port));
        host("172.20.10.222");

        final String dicHome = System.getProperty("dic.home", APP_HOME + "/config/dics");
        final Sensitives sens = Sensitives.singleton(dicHome);


        final Route wordFilterRoute = (request, response) -> {

            response.contentType("application/json");

            String body = request.body();
            JSONObject bodyObject = JSON.parseObject(body);

            String action = bodyObject.getString("action");
            String level = bodyObject.getString("level");
            String data = bodyObject.getString("data");

            switch (action) {
                default:
                case "verify": {
                    Set<String> sensitives = sens.judge(level,data);
                    if (sensitives.isEmpty()) return new ResponseVO(true);
                    else return new ResponseVO(sensitives);
                }
                case "replace": {
                    Optional<String> mosaic = sens.mosaic(level,data);
                    if (!mosaic.isPresent()) return new ResponseVO(true);
                    else return new ResponseVO(mosaic.get());
                }
            }
        };

        post("/security", (request, response) -> {
            long start = System.currentTimeMillis();

            String appId = request.params("appId");
            String subject = request.params("subject");

            Object re;
            switch (subject) {
                default:
                case "content_filter":
                    re = wordFilterRoute.apply(request, response);
                case "params_convert":
                    re = wordFilterRoute.apply(request, response);
            }

            Object o = re;
            Logs.info(() -> "APP:" + appId +
                    ",CONSUME:" + request.body() +
                    ",PRODUCE:" + o +
                    ",COST:" + (System.currentTimeMillis() - start) + "ms.");

            //TODO:
            return re;
        }, (o) -> JSON.toJSONString(o));


        // 判断是否合法，返回敏感词列表
        post("/filter/:appName/verify", (request, response) -> {

            String appName = request.params("appName");
            response.contentType("application/json");

            long start = System.currentTimeMillis();
            String content = request.body();
            Set<String> sensitives = sens.judge("",content);

            Logs.info(() -> "APP:" + appName +
                    ",CONSUME:" + content +
                    ",PRODUCE:" + sensitives +
                    ",COST:" + (System.currentTimeMillis() - start) + "ms.");

            if (sensitives.isEmpty()) return new ResponseVO(true);
            else return new ResponseVO(sensitives);

        }, (o) -> JSON.toJSONString(o));
        // 打马赛克，替换敏感词
        post("/filter/:appName/replace", wordFilterReplace(sens), (o) -> JSON.toJSONString(o));
    }

    // 输入：/security?appId=""&subject=
    // {action:'',level:''，data:''}

    static Route wordFilterVerify(Sensitives sens) {
        return (request, response) -> {

            String appName = request.params("appName");
            response.contentType("application/json");

            long start = System.currentTimeMillis();
            String content = request.body();
            Set<String> sensitives = sens.judge("",content);

            Logs.info(() -> "APP:" + appName +
                    ",CONSUME:" + content +
                    ",PRODUCE:" + sensitives +
                    ",COST:" + (System.currentTimeMillis() - start) + "ms.");

            if (sensitives.isEmpty()) return new ResponseVO(true);
            else return new ResponseVO(sensitives);

        };
    }

    static Route wordFilterReplace(Sensitives sens) {
        return (request, response) -> {

            String appName = request.params("appName");
            response.contentType("application/json");

            String content = request.body();
            Optional<String> mosaic = sens.mosaic("",content);

            long start = System.currentTimeMillis();
            Logs.info(() -> "APP:" + appName +
                    ",CONSUME:" + content +
                    ",PRODUCE:" + mosaic +
                    ",COST:" + (System.currentTimeMillis() - start) + "ms.");

            if (!mosaic.isPresent()) return new ResponseVO(true);
            else return new ResponseVO(mosaic.get());

        };
    }

    static void config() {
        try {
            APP_HOME = System.getProperty("app.home");

            Properties props = new Properties();
            props.load(new FileInputStream(APP_HOME + "/config/wordfilter.properties"));
            props.forEach((k, v) -> System.setProperty(String.valueOf(k), String.valueOf(v)));

            File logbackConfig = new File(APP_HOME + "/config/logback.xml");
            if (logbackConfig.exists()) {
                LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
                JoranConfigurator configurator = new JoranConfigurator();
                configurator.setContext(lc);
                lc.reset();
                try {
                    configurator.doConfigure(logbackConfig);
                } catch (JoranException e) {
                    Logs.error("logback config error: ", e);
                }
            }
        } catch (Exception e) {
            Logs.error("config error: ", e);
        }
    }


    /**
     * {"legalContent":true, "illegalWords":[]}
     * {"legalContent":false,"illegalWords":["职业报仇","pcp气枪网","枪","气枪"]}
     */
    public static class ResponseVO {
        Set<String> illegalWords;
        String legalContent;
        boolean isLegal;

        ResponseVO(Set<String> illegalWords) {
            this.illegalWords = illegalWords;
        }

        ResponseVO(String legalContent) {
            this.legalContent = legalContent;
        }

        ResponseVO(boolean isLegal) {
            this.isLegal = isLegal;
        }

        public Boolean isLegal() {
//            if (mosaic != null) return null;
//            return sensitives == null || sensitives.isEmpty();
            return isLegal;
        }

        public Set<String> getIllegalWords() {
            return illegalWords;
        }

        public String getLegalContent() {
            return legalContent;
        }
    }

}